#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "hal_serial.h"

static char *cr_lf = "\r\n";

void usage(const char *arg0) {
    fprintf(stderr, "Usage: %s -f -b -d -s -p --raw -r AT+CMD\n"
                    "\t-f --filename </dev/ttyUSB2>\n"
                    "\t-b --baud_rate <115200>\n"
                    "\t-d --data_bits <8>\n"
                    "\t-s --stop_bits <1>\n"
                    "\t-p --parity <N|O|E>\n"
                    "\t--none --odd --even\n"
                    "\t--raw\n"
                    "\t-r\t\tsplit colon[:]\n", strrchr(arg0, '/') + 1);
}

int write_cmd(SerialPort serial, uint8_t *buf) {
    int rc;

    for (int i = 0; buf[i] != '\0'; ++i) {
        rc = SerialPort_write(serial, buf, i, 1);
        if (rc < 0) {
            return rc;
        }
    }
    for (int i = 0; i < 2; ++i) {
        rc = SerialPort_write(serial, cr_lf, i, 1);
        if (rc < 0) {
            return rc;
        }
    }

    return rc;
}

int read_result(SerialPort serial, char *buf, size_t len) {
    char *p = buf;
    char *e = buf + len;

    while (p < e) {
        int rc = SerialPort_readByte(serial);
        if (rc != -1) {
            *p++ = rc;
        } else {
            break;
        }
    }

    return p - buf;
}

int parse_result(_Bool raw, _Bool right, char *buf) {
    if (raw) {
        puts(buf);
        return EXIT_SUCCESS;
    } else {
        char *token = strtok(buf, cr_lf);//skip echo line
        while (NULL != (token = strtok(NULL, cr_lf))) {
            if (NULL != strstr(token, "ERROR")) {
                return EXIT_FAILURE;
            } else if (0 == strcmp(token, "OK")) {
                return EXIT_SUCCESS;
            } else if ('\0' == token[0]) {
                continue;
            } else {
                if (right) {
                    char *p = strstr(token, ": ");
                    if (NULL != p) {
                        puts(p + 2);
                    } else {
                        puts(token);
                    }
                } else {
                    puts(token);
                }
            }
        }
    }

    return EXIT_FAILURE;
}

int main(int argc, char *argv[]) {
    int rc = EXIT_FAILURE;

    if (argc == 1) {
        usage(argv[0]);
        return EXIT_FAILURE;
    }

    char *filename = "/dev/ttyUSB2";
    int baud_rate = 115200;
    int data_bits = 8;
    int stop_bits = 1;
    char parity = 'N';

    _Bool raw = false;
    _Bool right = false;

    char *cmd = argv[argc - 1];

    for (int i = 1; i < argc - 1; ++i) {
        if (0 == strcmp(argv[i], "-f") || 0 == strcmp(argv[i], "--filename")) {
            filename = argv[++i];
        } else if (0 == strcmp(argv[i], "-b") || 0 == strcmp(argv[i], "--baud_rate")) {
            baud_rate = atoi(argv[++i]);
        } else if (0 == strcmp(argv[i], "-d") || 0 == strcmp(argv[i], "--data_bits")) {
            data_bits = atoi(argv[++i]);
        } else if (0 == strcmp(argv[i], "-s") || 0 == strcmp(argv[i], "--stop_bits")) {
            stop_bits = atoi(argv[++i]);
        } else if (0 == strcmp(argv[i], "-p") || 0 == strcmp(argv[i], "--parity")) {
            parity = argv[++i][0];
        } else if (0 == strcmp(argv[i], "--none")) {
            parity = 'N';
        } else if (0 == strcmp(argv[i], "--odd")) {
            parity = 'O';
        } else if (0 == strcmp(argv[i], "--even")) {
            parity = 'E';
        } else if (0 == strcmp(argv[i], "--raw")) {
            raw = true;
        } else if (0 == strcmp(argv[i], "-r")) {
            right = true;
        }
    }

    SerialPort serial = SerialPort_create(filename, baud_rate, data_bits, parity, stop_bits);
    if (!SerialPort_open(serial)) {
        SerialPortError err = SerialPort_getLastError(serial);
        fprintf(stderr, "SerialPort_open=%d\n", err);
        goto err;
    }

    rc = write_cmd(serial, cmd);
    if (rc < 0) goto err;

    char buf[256] = {};
    read_result(serial, buf, sizeof(buf));

    rc = parse_result(raw, right, buf);

    err:
    SerialPort_close(serial);
    SerialPort_destroy(serial);

    return rc;
}